using System;
using System.ComponentModel;
using System.Data;
using System.Web.UI;

namespace MyControls.DataSources.CompositeHierarchicalDataSource {
    /// <summary>
    /// a declarative relation object
    /// </summary>
    public sealed class Relation : IStateManager {
        private bool _isTrackingViewState;
        private CompositeHierarchicalDataSource _owner;
        private DataRelation _relation;
        private string _parentDataSourceId;
        private string _parentView;
        private string[] _parentColumns;
        private string _childDataSourceId;
        private string _childView;
        private string[] _childColumns;

        public Relation() {
        }

        /// <summary>
        /// Creates a Relation object with the specified owner.
        /// </summary>
        /// <param name="owner">The <see cref="CompositeHierarchicalDataSource"/> that owns the Relation.</param>
        internal Relation(CompositeHierarchicalDataSource owner)
            : this() {
            _owner = owner;
        }

        /// <summary>
        /// The ID of the child data source in the relation.
        /// </summary>
        public string ChildDataSourceId {
            get {
                return _childDataSourceId;
            }
            set {
                _childDataSourceId = value;
                _relation = null;
            }
        }

        /// <summary>
        /// The columns of the child view that must match the parent columns.
        /// </summary>
        [TypeConverter(typeof(ColumnNamesConverter))]
        public string[] ChildColumns {
            get {
                return _childColumns;
            }
            set {
                _childColumns = value;
                _relation = null;
            }
        }

        /// <summary>
        /// The name of the child view in the relation.
        /// </summary>
        public string ChildView {
            get {
                return _childView;
            }
            set {
                _childView = value;
                _relation = null;
            }
        }

        /// <summary>
        /// The ID of the parent data source in the relation.
        /// </summary>
        public string ParentDataSourceId {
            get {
                return _parentDataSourceId;
            }
            set {
                _parentDataSourceId = value;
                _relation = null;
            }
        }

        /// <summary>
        /// The name of the parent view in the relation.
        /// </summary>
        /// <value></value>
        public string ParentView {
            get {
                return _parentView;
            }
            set {
                _parentView = value;
                _relation = null;
            }
        }

        /// <summary>
        /// The columns of the parent view that must match the child columns.
        /// </summary>
        [TypeConverter(typeof(ColumnNamesConverter))]
        public string[] ParentColumns {
            get {
                return _parentColumns;
            }
            set {
                _parentColumns = value;
                _relation = null;
            }
        }

        /// <summary>
        /// Gets the internal <see cref="DataRelation"/>.
        /// </summary>
        /// <returns>The internal <see cref="DataRelation"/> for this Relation.</returns>
        internal DataRelation GetRelation() {
            if (_relation == null) {
                DataSet dataSet = _owner.DataSet;
                DataTable parentTable = dataSet.Tables[_parentView, _parentDataSourceId];
                DataTable childTable = dataSet.Tables[_childView, _childDataSourceId];
                DataColumn[] parentColumns = new DataColumn[ParentColumns.Length];
                for (int i = 0; i < parentColumns.Length; i++) {
                    parentColumns[i] = parentTable.Columns[ParentColumns[i]];
                }
                DataColumn[] childColumns = new DataColumn[ChildColumns.Length];
                for (int i = 0; i < childColumns.Length; i++) {
                    childColumns[i] = childTable.Columns[ChildColumns[i]];
                }
                _relation = dataSet.Relations.Add(parentColumns, childColumns);
            }
            return _relation;
        }

        /// <summary>
        /// Signals that something has changed and that the underlying <see cref="DataRelation"/> should be reset.
        /// </summary>
        public void SetDirty() {
            _relation = null;
        }

        /// <summary>
        /// Sets the owner of this Relation.
        /// </summary>
        /// <param name="owner">The <see cref="CompositeHierarchicalDataSource"/> that owns this Relation.</param>
        internal void SetOwner(CompositeHierarchicalDataSource owner) {
            _owner = owner;
        }

        #region IStateManager Members
        bool IStateManager.IsTrackingViewState {
            get {
                return _isTrackingViewState;
            }
        }


        void IStateManager.LoadViewState(object state) {
            object[] arrayState = state as object[];
            if (arrayState != null && arrayState.Length == 6) {
                _parentDataSourceId = (string)arrayState[0];
                _parentView = (string)arrayState[1];
                _parentColumns = (string[])arrayState[2];
                _childDataSourceId = (string)arrayState[3];
                _childView = (string)arrayState[4];
                _childColumns = (string[])arrayState[5];
            }
        }

        object IStateManager.SaveViewState() {
            return new object[] {
			_parentDataSourceId,
			_parentView,
			_parentColumns,
			_childDataSourceId,
			_childView,
			_childColumns};
        }

        void IStateManager.TrackViewState() {
            _isTrackingViewState = true;
        }

        #endregion
    }
}